<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta http-equiv="Cache-Control" content="no-siteapp">
  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
  <meta name="renderer" content="webkit">

  
  <title>Android13下拉状态栏QS面板的加载流程解析 | 龙之叶的博客</title>

  <link rel="shortcut icon" href="/images/favicon.png">
  <link rel="alternate" href="/atom.xml" title="龙之叶的博客" type="application/atom+xml">
  <meta name="description" content="Android13下拉状态栏QS面板的加载流程解析">
<meta property="og:type" content="article">
<meta property="og:title" content="Android13下拉状态栏QS面板的加载流程解析">
<meta property="og:url" content="http://longzhiye.top/2023/05/22/2023-05-22/index.html">
<meta property="og:site_name" content="龙之叶的博客">
<meta property="og:description" content="Android13下拉状态栏QS面板的加载流程解析">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://longzhiye.top/images/20230522/Screenshot_20230522-205519.jpg">
<meta property="article:published_time" content="2023-05-21T16:00:00.000Z">
<meta property="article:modified_time" content="2024-08-29T02:40:34.905Z">
<meta property="article:author" content="龙之叶">
<meta property="article:tag" content="Android">
<meta property="article:tag" content="Framework">
<meta property="article:tag" content="SystemUI">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://longzhiye.top/images/20230522/Screenshot_20230522-205519.jpg">

  <meta name="keywords" content=",Android,Framework,SystemUI">
  <meta name="format-detection" content="telephone=no,email=no">
  <meta name="theme-color" content="#9C27B0">

  <meta name="mobile-web-app-capable" content="yes">
  <meta name="application-name" content="龙之叶的博客">
  <meta name="msapplication-starturl" content="http://longzhiye.top/2023/05/22/2023-05-22/">
  <meta name="msapplication-navbutton-color" content="#9C27B0">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-title" content="龙之叶的博客">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <link rel="apple-touch-icon" href="/images/favicon.png">

  
    <link rel="canonical" href="http://longzhiye.top/2023/05/22/2023-05-22/">
  

  
  

  
  
  

  
<link rel="stylesheet" href="/css/mdui.css">
<link rel="stylesheet" href="/css/style.css">

  
<link rel="stylesheet" href="/custom.css">

<meta name="generator" content="Hexo 5.4.2"></head>

<body class="mdui-appbar-with-toolbar mdui-theme-primary-indigo mdui-theme-accent-pink">
  <script>var a=localStorage.getItem("mdui-theme-layout-dark");if(a){document.getElementsByTagName("body")[0].className+=" mdui-theme-layout-dark"};</script>
  <script>if(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches){document.getElementsByTagName("body")[0].className+=" mdui-theme-layout-dark"};</script>
  <script>var a=localStorage.getItem("mdui-drawer-close");if(!a){document.getElementsByTagName("body")[0].className+=" mdui-drawer-body-left"};</script>
  <header id="header" class="mdui-appbar mdui-appbar-fixed mdui-appbar-scroll-hide mdui-appbar-inset">
  <div class="mdui-toolbar mdui-color-theme">
    <a href="javascript:;" class="mdui-btn mdui-btn-icon" mdui-drawer="{target: '#sidebar', swipe: true}"><i class="mdui-icon material-icons">menu</i></a>
    <a href="/" class="mdui-typo-headline">龙之叶的博客</a>
    <div class="mdui-toolbar-spacer"></div>
    <a href="javascript:;" class="mdui-btn mdui-btn-icon" mdui-dialog="{target: '#search'}" mdui-tooltip="{content: '搜索'}"><i class="mdui-icon material-icons">search</i></a>
	<!--
    <a href="/atom.xml" class="mdui-btn mdui-btn-icon" mdui-tooltip="{content: 'RSS'}"><i class="mdui-icon material-icons">rss_feed</i></a>
	-->
  </div>
</header>
<div class="mdui-dialog" id="search">
  
    <div class="search-form">
      <input type="search" class="search-form-input" placeholder="请输入关键字">
    </div>
    <div class="search-result" data-resource="/search.xml"></div>
  
</div>

  <aside id="sidebar" class="mdui-drawer mdui-drawer-full-height">
  <script>var a=localStorage.getItem("mdui-drawer-close");if(a){document.getElementById("sidebar").className+=" mdui-drawer-close"};</script>
  <div class="mdui-grid-tile">
    <img src="/images/banner.png" style="height: 160px;">
    <img src="/images/avatar.png" class="avatar-animation" style="position: absolute; top: 10%; left: 24px; width: 64px; height: 64px; border: 2px solid #fff; border-radius: 50%;background-color:#fff;">
    <div class="mdui-grid-tile-actions">
      <div class="mdui-grid-tile-text">
        <div class="mdui-grid-tile-title">龙之叶</div>
        <div class="mdui-grid-tile-subtitle"><i class="mdui-icon material-icons">art_track</i>生命不息，折腾不止</div>
      </div>
      
        <div class="mdui-grid-tile-buttons">
          <a href="mailto:longzhiye163@163.com" class="mdui-btn mdui-btn-icon" mdui-tooltip="{content: 'longzhiye163@163.com'}"><i class="mdui-icon material-icons">email</i></a>
        </div>
      
    </div>
  </div>

  <div class="mdui-list" mdui-collapse="{accordion: true}">
    <a href="/" class="mdui-list-item mdui-ripple">
      <i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-blue">home</i>
      <div class="mdui-list-item-content">主页</div>
    </a>
    <div class="mdui-collapse-item">
      <script>var a=localStorage.getItem("mdui-collapse-item-0");if(a){document.getElementsByClassName("mdui-collapse-item")[0].className+=" mdui-collapse-item-open"};</script>
      <div class="mdui-collapse-item-header mdui-list-item mdui-ripple">
        <i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-deep-orange">archive</i>
        <div class="mdui-list-item-content">归档</div>
        <i class="mdui-collapse-item-arrow mdui-icon material-icons">keyboard_arrow_down</i>
      </div>
      <div class="mdui-collapse-item-body mdui-list mdui-list-dense">
        
        <a class="mdui-ripple sidebar_archives-link" href="/archives/2025/07/">七月 2025<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2025/06/">六月 2025<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2025/03/">三月 2025<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2025/02/">二月 2025<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2025/01/">一月 2025<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2024/10/">十月 2024<span class="mdui-ripple sidebar_archives-count">7</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2024/09/">九月 2024<span class="mdui-ripple sidebar_archives-count">4</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2024/08/">八月 2024<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2024/03/">三月 2024<span class="mdui-ripple sidebar_archives-count">5</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2024/02/">二月 2024<span class="mdui-ripple sidebar_archives-count">11</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2024/01/">一月 2024<span class="mdui-ripple sidebar_archives-count">9</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/12/">十二月 2023<span class="mdui-ripple sidebar_archives-count">10</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/11/">十一月 2023<span class="mdui-ripple sidebar_archives-count">8</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/10/">十月 2023<span class="mdui-ripple sidebar_archives-count">8</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/09/">九月 2023<span class="mdui-ripple sidebar_archives-count">3</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/08/">八月 2023<span class="mdui-ripple sidebar_archives-count">6</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/06/">六月 2023<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/05/">五月 2023<span class="mdui-ripple sidebar_archives-count">4</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/04/">四月 2023<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/03/">三月 2023<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2023/02/">二月 2023<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2022/09/">九月 2022<span class="mdui-ripple sidebar_archives-count">7</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2022/08/">八月 2022<span class="mdui-ripple sidebar_archives-count">4</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2017/04/">四月 2017<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2017/03/">三月 2017<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2017/02/">二月 2017<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2017/01/">一月 2017<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2016/12/">十二月 2016<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2016/11/">十一月 2016<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2016/10/">十月 2016<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/archives/2016/08/">八月 2016<span class="mdui-ripple sidebar_archives-count">1</span></a>
        
      </div>
    </div>
    <div class="mdui-collapse-item">
      <script>var a=localStorage.getItem("mdui-collapse-item-1");if(a){document.getElementsByClassName("mdui-collapse-item")[1].className+=" mdui-collapse-item-open"};</script>
      <div class="mdui-collapse-item-header mdui-list-item mdui-ripple">
        <i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-green">class</i>
        <div class="mdui-list-item-content">分类</div>
        <i class="mdui-collapse-item-arrow mdui-icon material-icons">keyboard_arrow_down</i>
      </div>
      <div class="mdui-collapse-item-body mdui-list mdui-list-dense">
        
        <a class="mdui-ripple sidebar_archives-link" href="/categories/%E6%8A%80%E6%9C%AF/">技术<span class="mdui-ripple sidebar_archives-count">98</span></a><a class="mdui-ripple sidebar_archives-link" href="/categories/%E7%94%9F%E6%B4%BB/">生活<span class="mdui-ripple sidebar_archives-count">3</span></a><a class="mdui-ripple sidebar_archives-link" href="/categories/%E8%B5%84%E8%AE%AF/">资讯<span class="mdui-ripple sidebar_archives-count">4</span></a><a class="mdui-ripple sidebar_archives-link" href="/categories/%E9%80%9A%E7%9F%A5/">通知<span class="mdui-ripple sidebar_archives-count">4</span></a>
        
      </div>
    </div>
    <div class="mdui-collapse-item">
      <script>var a=localStorage.getItem("mdui-collapse-item-2");if(a){document.getElementsByClassName("mdui-collapse-item")[2].className+=" mdui-collapse-item-open"};</script>
      <div class="mdui-collapse-item-header mdui-list-item mdui-ripple">
        <i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-brown">bookmark</i>
        <div class="mdui-list-item-content">标签</div>
        <i class="mdui-collapse-item-arrow mdui-icon material-icons">keyboard_arrow_down</i>
      </div>
      <div class="mdui-collapse-item-body mdui-list mdui-list-dense">
        
        <a class="mdui-ripple sidebar_archives-link" href="/tags/ANR/" rel="tag">ANR<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/APP/" rel="tag">APP<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Android/" rel="tag">Android<span class="mdui-ripple sidebar_archives-count">89</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Android12/" rel="tag">Android12<span class="mdui-ripple sidebar_archives-count">3</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Android13/" rel="tag">Android13<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Android14/" rel="tag">Android14<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/AndroidStudio/" rel="tag">AndroidStudio<span class="mdui-ripple sidebar_archives-count">3</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/AutoDraw/" rel="tag">AutoDraw<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Crash/" rel="tag">Crash<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Foxmail/" rel="tag">Foxmail<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Framework/" rel="tag">Framework<span class="mdui-ripple sidebar_archives-count">20</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/GPS%E8%BD%A8%E8%BF%B9%E5%9B%BE/" rel="tag">GPS轨迹图<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Git/" rel="tag">Git<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/GitHub/" rel="tag">GitHub<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Google/" rel="tag">Google<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Hexo/" rel="tag">Hexo<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Java/" rel="tag">Java<span class="mdui-ripple sidebar_archives-count">3</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Kernel/" rel="tag">Kernel<span class="mdui-ripple sidebar_archives-count">4</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Launcher/" rel="tag">Launcher<span class="mdui-ripple sidebar_archives-count">17</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Lib/" rel="tag">Lib<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Linux/" rel="tag">Linux<span class="mdui-ripple sidebar_archives-count">18</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Markdown/" rel="tag">Markdown<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Material-Design/" rel="tag">Material Design<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/OS-X/" rel="tag">OS X<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/OTA/" rel="tag">OTA<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/QuickTime/" rel="tag">QuickTime<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/SSH/" rel="tag">SSH<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Settings/" rel="tag">Settings<span class="mdui-ripple sidebar_archives-count">6</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/SystemUI/" rel="tag">SystemUI<span class="mdui-ripple sidebar_archives-count">19</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Ubuntu/" rel="tag">Ubuntu<span class="mdui-ripple sidebar_archives-count">7</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/WPS/" rel="tag">WPS<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Wifi/" rel="tag">Wifi<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/WindTerm/" rel="tag">WindTerm<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/Windows/" rel="tag">Windows<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/androidmk/" rel="tag">androidmk<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/blog/" rel="tag">blog<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/build/" rel="tag">build<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/feel/" rel="tag">feel<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/framework/" rel="tag">framework<span class="mdui-ripple sidebar_archives-count">50</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/git/" rel="tag">git<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/inotify/" rel="tag">inotify<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/life/" rel="tag">life<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/ninja/" rel="tag">ninja<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/rsync/" rel="tag">rsync<span class="mdui-ripple sidebar_archives-count">2</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/standard/" rel="tag">standard<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/test/" rel="tag">test<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1/" rel="tag">企业微信<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" rel="tag">操作系统<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/%E6%B5%8B%E8%AF%95/" rel="tag">测试<span class="mdui-ripple sidebar_archives-count">1</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/%E6%BA%90%E7%A0%81/" rel="tag">源码<span class="mdui-ripple sidebar_archives-count">3</span></a><a class="mdui-ripple sidebar_archives-link" href="/tags/%E7%94%9F%E6%B4%BB%E6%84%9F%E6%82%9F/" rel="tag">生活感悟<span class="mdui-ripple sidebar_archives-count">1</span></a>
        
      </div>
    </div>
    <a href="/about" class="mdui-list-item mdui-ripple">
      <i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-purple">person</i>
      <div class="mdui-list-item-content">关于</div>
    </a>
  </div>

  <div class="mdui-divider"></div>

  <div class="mdui-list" mdui-collapse="{accordion: true}">
    
      <a href="/timeline" class="mdui-list-item mdui-ripple">时间轴</a>
    
    <div class="mdui-collapse-item">
      <script>var a=localStorage.getItem("mdui-collapse-item-3");if(a){document.getElementsByClassName("mdui-collapse-item")[3].className+=" mdui-collapse-item-open"};</script>
      <div class="mdui-collapse-item-header mdui-list-item mdui-ripple">
        <div class="mdui-list-item-content">友情链接</div>
        <i class="mdui-list-item-icon mdui-icon material-icons">link</i>
      </div>
      <div class="mdui-collapse-item-body mdui-list mdui-list-dense">
        
          <a href="http://www.niemingzhao.top" target="_blank" class="mdui-list-item mdui-p-l-2 mdui-text-color-theme-accent mdui-ripple" style="justify-content: center;">聂明照的博客</a>
        
        
      </div>
    </div>
  </div>
</aside>

  <main id="main" class="mdui-m-t-5 fadeIn animated">
  
<link rel="stylesheet" href="//cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css">

  <style>#main article .mdui-card-content .center-block{display:block!important;margin-right:auto!important;margin-left:auto!important}</style>
  <style>#main article .mdui-card-content .text-center{text-align:center!important}</style>
  <article class="mdui-card mdui-m-b-5">
    <header class="mdui-card-media">
      <img src="/images/random/material-12.png" style="max-height: 240px;">
      <div class="mdui-card-media-covered">
        <div class="mdui-card-primary">
          <div class="mdui-card-primary-title">Android13下拉状态栏QS面板的加载流程解析</div>
          <div class="mdui-card-primary-subtitle"><i class="iconfont">&#xe697;</i> 2023-05-22 / <i class="iconfont">&#xe601;</i> 龙之叶 &nbsp;&nbsp; <span id="busuanzi_container_page_pv" style="display: none;"><i class="iconfont">&#xe7fd;</i> <span id="busuanzi_value_page_pv"></span></span></div>
        </div>
      </div>
      <div class="mdui-card-menu">
        
          <button class="mdui-btn mdui-btn-icon mdui-text-color-white" mdui-menu="{target: '#qrcode', align: 'right'}"><i class="mdui-icon material-icons">devices</i></button>
          <ul class="mdui-menu" id="qrcode">
            
              <li class="mdui-menu-item"><a class="mdui-text-center mdui-ripple">发送到手机</a></li>
            
            <li class="mdui-menu-item" disabled>
              
                <img src="//qr.liantu.com/api.php?w=246&m=10&text=http://longzhiye.top/2023/05/22/2023-05-22/">
              
            </li>
          </ul>
        
        
          <button class="mdui-btn mdui-btn-icon mdui-text-color-white" mdui-menu="{target: '#share_menu', align: 'right'}"><i class="mdui-icon material-icons">share</i></button>
          <ul class="mdui-menu" id="share_menu">
            <li class="mdui-menu-item">
              <a href="https://service.weibo.com/share/share.php?appkey=&title=Android13下拉状态栏QS面板的加载流程解析&url=http://longzhiye.top/2023/05/22/2023-05-22/&pic=http://longzhiye.top/images/favicon.png&searchPic=false&style=simple" target="_blank" class="mdui-ripple">分享到 Weibo</a>
            </li>
            <li class="mdui-menu-item">
              <a href="https://twitter.com/intent/tweet?text=Android13下拉状态栏QS面板的加载流程解析&url=http://longzhiye.top/2023/05/22/2023-05-22/&via=龙之叶" target="_blank" class="mdui-ripple">分享到 Twitter</a>
            </li>
            <li class="mdui-menu-item">
              <a href="https://www.facebook.com/sharer/sharer.php?u=http://longzhiye.top/2023/05/22/2023-05-22/" target="_blank" class="mdui-ripple">分享到 Facebook</a>
            </li>
            <li class="mdui-menu-item">
              <a href="https://plus.google.com/share?url=http://longzhiye.top/2023/05/22/2023-05-22/" target="_blank" class="mdui-ripple">分享到 Google+</a>
            </li>
            <li class="mdui-menu-item">
              <a href="https://www.linkedin.com/shareArticle?mini=true&url=http://longzhiye.top/2023/05/22/2023-05-22/&title=Android13下拉状态栏QS面板的加载流程解析" target="_blank" class="mdui-ripple">分享到 LinkedIn</a>
            </li>
            <li class="mdui-menu-item">
              <a href="https://connect.qq.com/widget/shareqq/index.html?site=龙之叶的博客&title=Android13下拉状态栏QS面板的加载流程解析&pics=http://longzhiye.top/images/favicon.png&url=http://longzhiye.top/2023/05/22/2023-05-22/" target="_blank" class="mdui-ripple">分享到 QQ</a>
            </li>
            <li class="mdui-menu-item">
              <a href="https://telegram.me/share/url?url=http://longzhiye.top/2023/05/22/2023-05-22/&text=Android13下拉状态栏QS面板的加载流程解析" target="_blank" class="mdui-ripple">分享到 Telegram</a>
            </li>
          </ul>
        
      </div>
    </header>
    <div class="mdui-card-content mdui-typo">
      <h2 id="1、QS创建"><a href="#1、QS创建" class="headerlink" title="1、QS创建"></a>1、QS创建</h2><p>QSPanel 创建是从 CentralSurfacesImpl#makeStatusBarView 开始的，Qs面板创建这块，与之前版本对比，没啥变化。<br><strong>com.android.systemui.statusbar.phone.CentralSurfacesImpl.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">makeStatusBarView</span><span class="params">()</span> &#123;</span><br><span class="line">      ......</span><br><span class="line">      <span class="comment">// 设置快速设置面板</span></span><br><span class="line">      <span class="comment">// R.id.qs_frame 是一个 FrameLayout 布局，将 QSFragment 布局添加到其中。所以 R.id.qs_frame 最终显示的是 QSFragment 。</span></span><br><span class="line">      <span class="keyword">final</span> <span class="type">View</span> <span class="variable">container</span> <span class="operator">=</span> mNotificationShadeWindowView.findViewById(R.id.qs_frame);</span><br><span class="line">      <span class="keyword">if</span> (container != <span class="literal">null</span>) &#123;</span><br><span class="line">          <span class="type">FragmentHostManager</span> <span class="variable">fragmentHostManager</span> <span class="operator">=</span> FragmentHostManager.get(container);</span><br><span class="line">          ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,</span><br><span class="line">                  mExtensionController</span><br><span class="line">                          .newExtension(QS.class)</span><br><span class="line">                          .withPlugin(QS.class)</span><br><span class="line">                          .withDefault(<span class="built_in">this</span>::createDefaultQSFragment)</span><br><span class="line">                          .build());</span><br><span class="line">          <span class="comment">// 亮度控制器</span></span><br><span class="line">          mBrightnessMirrorController = <span class="keyword">new</span> <span class="title class_">BrightnessMirrorController</span>(</span><br><span class="line">                  mNotificationShadeWindowView,</span><br><span class="line">                  mNotificationPanelViewController,</span><br><span class="line">                  mNotificationShadeDepthControllerLazy.get(),</span><br><span class="line">                  mBrightnessSliderFactory,</span><br><span class="line">                  (visible) -&gt; &#123;</span><br><span class="line">                      mBrightnessMirrorVisible = visible;</span><br><span class="line">                      updateScrimController();</span><br><span class="line">                  &#125;);</span><br><span class="line">          fragmentHostManager.addTagListener(QS.TAG, (tag, f) -&gt; &#123;</span><br><span class="line">              <span class="type">QS</span> <span class="variable">qs</span> <span class="operator">=</span> (QS) f;</span><br><span class="line">              <span class="keyword">if</span> (qs <span class="keyword">instanceof</span> QSFragment) &#123;</span><br><span class="line">                  mQSPanelController = ((QSFragment) qs).getQSPanelController();</span><br><span class="line">                  ((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController);</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">      ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>接下来就先看看 QSFragment 的 onCreateView() 方法：<br><strong>com.android.systemui.qs.QSFragment.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">......</span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> View <span class="title function_">onCreateView</span><span class="params">(LayoutInflater inflater, <span class="meta">@Nullable</span> ViewGroup container,</span></span><br><span class="line"><span class="params">        Bundle savedInstanceState)</span> &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        Trace.beginSection(<span class="string">&quot;QSFragment#onCreateView&quot;</span>);</span><br><span class="line">        inflater = inflater.cloneInContext(<span class="keyword">new</span> <span class="title class_">ContextThemeWrapper</span>(getContext(),</span><br><span class="line">                R.style.Theme_SystemUI_QuickSettings));</span><br><span class="line">        <span class="comment">// 在这里返回了布局，R.layout.qs_panel</span></span><br><span class="line">        <span class="keyword">return</span> inflater.inflate(R.layout.qs_panel, container, <span class="literal">false</span>);</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        Trace.endSection();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">......</span><br></pre></td></tr></table></figure>
<p>再看 QSFragment 的构造函数：<br><strong>com.android.systemui.qs.QSFragment.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">......</span><br><span class="line"><span class="meta">@Inject</span></span><br><span class="line"><span class="keyword">public</span> <span class="title function_">QSFragment</span><span class="params">(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,</span></span><br><span class="line"><span class="params">        QSTileHost qsTileHost,</span></span><br><span class="line"><span class="params">        StatusBarStateController statusBarStateController, CommandQueue commandQueue,</span></span><br><span class="line"><span class="params">        <span class="meta">@Named(QS_PANEL)</span> MediaHost qsMediaHost,</span></span><br><span class="line"><span class="params">        <span class="meta">@Named(QUICK_QS_PANEL)</span> MediaHost qqsMediaHost,</span></span><br><span class="line"><span class="params">        KeyguardBypassController keyguardBypassController,</span></span><br><span class="line"><span class="params">        QSFragmentComponent.Factory qsComponentFactory,</span></span><br><span class="line"><span class="params">        QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,</span></span><br><span class="line"><span class="params">        FalsingManager falsingManager, DumpManager dumpManager)</span> &#123;</span><br><span class="line">    ......</span><br><span class="line">    mHost = qsTileHost;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br><span class="line">......</span><br></pre></td></tr></table></figure>
<p>这里注意 @Inject 注解，这个是 Android dagger里的一种注解。<br>在这里，与Android 9.0及其以下版本实例化 QSTileHost类的方式不一样，这里是通dagger来实例化的。所以这里实例化了QSTileHost 。<br>下面我们就进入到 QSTileHost 的构造方法：<br><strong>com.android.systemui.qs.QSTileHost.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">......</span><br><span class="line"><span class="meta">@Inject</span></span><br><span class="line"><span class="keyword">public</span> <span class="title function_">QSTileHost</span><span class="params">(Context context,</span></span><br><span class="line"><span class="params">        StatusBarIconController iconController,</span></span><br><span class="line"><span class="params">        QSFactory defaultFactory,</span></span><br><span class="line"><span class="params">        <span class="meta">@Main</span> Handler mainHandler,</span></span><br><span class="line"><span class="params">        <span class="meta">@Background</span> Looper bgLooper,</span></span><br><span class="line"><span class="params">        PluginManager pluginManager,</span></span><br><span class="line"><span class="params">        TunerService tunerService,</span></span><br><span class="line"><span class="params">        Provider&lt;AutoTileManager&gt; autoTiles,</span></span><br><span class="line"><span class="params">        DumpManager dumpManager,</span></span><br><span class="line"><span class="params">        BroadcastDispatcher broadcastDispatcher,</span></span><br><span class="line"><span class="params">        Optional&lt;CentralSurfaces&gt; centralSurfacesOptional,</span></span><br><span class="line"><span class="params">        QSLogger qsLogger,</span></span><br><span class="line"><span class="params">        UiEventLogger uiEventLogger,</span></span><br><span class="line"><span class="params">        UserTracker userTracker,</span></span><br><span class="line"><span class="params">        SecureSettings secureSettings,</span></span><br><span class="line"><span class="params">        CustomTileStatePersister customTileStatePersister,</span></span><br><span class="line"><span class="params">        TileServiceRequestController.Builder tileServiceRequestControllerBuilder,</span></span><br><span class="line"><span class="params">        TileLifecycleManager.Factory tileLifecycleManagerFactory</span></span><br><span class="line"><span class="params">)</span> &#123;</span><br><span class="line">    ......</span><br><span class="line">    mainHandler.post(() -&gt; &#123;</span><br><span class="line">        <span class="comment">// This is technically a hack to avoid circular dependency of</span></span><br><span class="line">        <span class="comment">// QSTileHost -&gt; XXXTile -&gt; QSTileHost. Posting ensures creation</span></span><br><span class="line">        <span class="comment">// 在创建任何图块之前完成。</span></span><br><span class="line">        tunerService.addTunable(<span class="built_in">this</span>, TILES_SETTING);</span><br><span class="line">        <span class="comment">// AutoTileManager 可以修改 mTiles，因此请确保 mTiles 已经初始化。</span></span><br><span class="line">        mAutoTiles = autoTiles.get();</span><br><span class="line">        mTileServiceRequestController.init();</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line">......</span><br></pre></td></tr></table></figure>
<p>在 QSTileHost 的构造函数里，我们主要看 tunerService.addTunable(this, TILES_SETTING); 很明显，调用 tunerService 里的 addTunabe() 方法，跟进去会发现，最终的是调用的 TunerServiceImpl 里面的 addTunabe() 方法。<br><strong>com.android.systemui.tuner.TunerServiceImpl.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">......</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addTunable</span><span class="params">(Tunable tunable, String... keys)</span> &#123;</span><br><span class="line">    <span class="keyword">for</span> (String key : keys) &#123;</span><br><span class="line">        addTunable(tunable, key);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">addTunable</span><span class="params">(Tunable tunable, String key)</span> &#123;</span><br><span class="line">    ......</span><br><span class="line">    <span class="comment">// 从数据库读取数据；刷机第一次数据库为空，这里也会空，后面程序会从配置文件读取；</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">value</span> <span class="operator">=</span> DejankUtils.whitelistIpcs(() -&gt; Settings.Secure</span><br><span class="line">            .getStringForUser(mContentResolver, key, mCurrentUser));</span><br><span class="line">    tunable.onTuningChanged(key, value);</span><br><span class="line">&#125;</span><br><span class="line">......</span><br></pre></td></tr></table></figure>
<p>tunable.onTuningChanged() 回调 QSTileHost#onTuningChanged():<br><strong>com.android.systemui.qs.QSTileHost.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onTuningChanged</span><span class="params">(String key, String newValue)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (!TILES_SETTING.equals(key)) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (DEBUG) Log.d(TAG, <span class="string">&quot;Recreating tiles&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (newValue == <span class="literal">null</span> &amp;&amp; UserManager.isDeviceInDemoMode(mContext)) &#123;</span><br><span class="line">        newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//调用 QSTileHost#loadTileSpecs，获得 config 里字符串信息</span></span><br><span class="line">    <span class="keyword">final</span> List&lt;String&gt; tileSpecs = loadTileSpecs(mContext, newValue);</span><br><span class="line">    <span class="type">int</span> <span class="variable">currentUser</span> <span class="operator">=</span> ActivityManager.getCurrentUser();</span><br><span class="line">    <span class="keyword">if</span> (tileSpecs.equals(mTileSpecs) &amp;&amp; currentUser == mCurrentUser) <span class="keyword">return</span>;</span><br><span class="line">    <span class="comment">//进行了过滤</span></span><br><span class="line">    mTiles.entrySet().stream().filter(tile -&gt; !tileSpecs.contains(tile.getKey())).forEach(</span><br><span class="line">            tile -&gt; &#123;</span><br><span class="line">                <span class="keyword">if</span> (DEBUG) Log.d(TAG, <span class="string">&quot;Destroying tile: &quot;</span> + tile.getKey());</span><br><span class="line">                tile.getValue().destroy();</span><br><span class="line">            &#125;);</span><br><span class="line">    <span class="keyword">final</span> LinkedHashMap&lt;String, QSTile&gt; newTiles = <span class="keyword">new</span> <span class="title class_">LinkedHashMap</span>&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span> (String tileSpec : tileSpecs) &#123;</span><br><span class="line">        <span class="type">QSTile</span> <span class="variable">tile</span> <span class="operator">=</span> mTiles.get(tileSpec);</span><br><span class="line">        <span class="keyword">if</span> (tile != <span class="literal">null</span> &amp;&amp; (!(tile <span class="keyword">instanceof</span> CustomTile)</span><br><span class="line">                || ((CustomTile) tile).getUser() == currentUser)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (tile.isAvailable()) &#123;</span><br><span class="line">                <span class="keyword">if</span> (DEBUG) Log.d(TAG, <span class="string">&quot;Adding &quot;</span> + tile);</span><br><span class="line">                tile.removeCallbacks();</span><br><span class="line">                <span class="keyword">if</span> (!(tile <span class="keyword">instanceof</span> CustomTile) &amp;&amp; mCurrentUser != currentUser) &#123;</span><br><span class="line">                    tile.userSwitch(currentUser);</span><br><span class="line">                &#125;</span><br><span class="line">                newTiles.put(tileSpec, tile);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                tile.destroy();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (DEBUG) Log.d(TAG, <span class="string">&quot;Creating tile: &quot;</span> + tileSpec);</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">//这里通过 字符串 一个个实例化 Tile</span></span><br><span class="line">                tile = createTile(tileSpec);</span><br><span class="line">                <span class="keyword">if</span> (tile != <span class="literal">null</span>) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (tile.isAvailable()) &#123;</span><br><span class="line">                        tile.setTileSpec(tileSpec);</span><br><span class="line">                        <span class="comment">// put 到 Map 中</span></span><br><span class="line">                        newTiles.put(tileSpec, tile);</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        tile.destroy();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (Throwable t) &#123;</span><br><span class="line">                Log.w(TAG, <span class="string">&quot;Error creating tile for spec: &quot;</span> + tileSpec, t);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    mCurrentUser = currentUser;</span><br><span class="line">    mTileSpecs.clear();</span><br><span class="line">    mTileSpecs.addAll(tileSpecs);</span><br><span class="line">    mTiles.clear();</span><br><span class="line">    <span class="comment">// put 到 Map 中</span></span><br><span class="line">    mTiles.putAll(newTiles);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; mCallbacks.size(); i++) &#123;</span><br><span class="line">        <span class="comment">//注册，当开发状态改变时回调</span></span><br><span class="line">        mCallbacks.get(i).onTilesChanged();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里有两个重要的方法：一个是获取 config 里字符串信息 loadTileSpecs(mContext, newValue)；一个实例化 Tile 的 createTile(tileSpec)。<br>先看第一个 QSTileHost#loadTileSpecs() 这里和Android 10 有点出入。<br><strong>com.android.systemui.qs.QSTileHost.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="keyword">static</span> List&lt;String&gt; <span class="title function_">loadTileSpecs</span><span class="params">(Context context, String tileList)</span> &#123;</span><br><span class="line">    <span class="keyword">final</span> <span class="type">Resources</span> <span class="variable">res</span> <span class="operator">=</span> context.getResources();</span><br><span class="line">    <span class="comment">// tileList 为空，则获取一个 “default” 字符串</span></span><br><span class="line">    <span class="keyword">if</span> (TextUtils.isEmpty(tileList)) &#123;</span><br><span class="line">        tileList = res.getString(R.string.quick_settings_tiles);</span><br><span class="line">        <span class="keyword">if</span> (DEBUG) Log.d(TAG, <span class="string">&quot;Loaded tile specs from config: &quot;</span> + tileList);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (DEBUG) Log.d(TAG, <span class="string">&quot;Loaded tile specs from setting: &quot;</span> + tileList);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">final</span> ArrayList&lt;String&gt; tiles = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;String&gt;();</span><br><span class="line">    <span class="type">boolean</span> <span class="variable">addedDefault</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">    Set&lt;String&gt; addedSpecs = <span class="keyword">new</span> <span class="title class_">ArraySet</span>&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span> (String tile : tileList.split(<span class="string">&quot;,&quot;</span>)) &#123;</span><br><span class="line">        tile = tile.trim();</span><br><span class="line">        <span class="keyword">if</span> (tile.isEmpty()) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="comment">// 第一次 tileList 为空，取了默认值，</span></span><br><span class="line">        <span class="keyword">if</span> (tile.equals(<span class="string">&quot;default&quot;</span>)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!addedDefault) &#123;</span><br><span class="line">                <span class="comment">// 从 config 文件获取</span></span><br><span class="line">                List&lt;String&gt; defaultSpecs = getDefaultSpecs(context);</span><br><span class="line">                <span class="keyword">for</span> (String spec : defaultSpecs) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (!addedSpecs.contains(spec)) &#123;</span><br><span class="line">                        tiles.add(spec);</span><br><span class="line">                        addedSpecs.add(spec);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">                addedDefault = <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (!addedSpecs.contains(tile)) &#123;</span><br><span class="line">                tiles.add(tile);</span><br><span class="line">                addedSpecs.add(tile);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 省略其他代码......</span></span><br><span class="line">    <span class="keyword">return</span> tiles;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上述代码中第一次 tileList 为空，调用了 getDefaultSpecs(context) 获取字符串，该方法比较简单，这里就不做分析了。<br>接着看第二个  QSTileHost#createTile(tileSpec) 方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> QSTile <span class="title function_">createTile</span><span class="params">(String tileSpec)</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; mQsFactories.size(); i++) &#123;</span><br><span class="line">            <span class="type">QSTile</span> <span class="variable">t</span> <span class="operator">=</span> mQsFactories.get(i).createTile(tileSpec);</span><br><span class="line">            <span class="keyword">if</span> (t != <span class="literal">null</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> t;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// M: @ &#123;</span></span><br><span class="line">        <span class="keyword">if</span> (mQuickSettingsExt != <span class="literal">null</span> &amp;&amp; mQuickSettingsExt.doOperatorSupportTile(tileSpec)) &#123;</span><br><span class="line">            <span class="comment">// WifiCalling</span></span><br><span class="line">            <span class="keyword">return</span> (QSTile) mQuickSettingsExt.createTile(<span class="built_in">this</span>, tileSpec);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// @ &#125;</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>这里调用 QSFactory#createTile()，而 QSFactory 接口又由 QSFactoryImpl 实现。所以这里直接看 QSFactoryImpl #createTile()：<br><strong>com.android.systemui.qs.tileimpl.QSFactoryImpl.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> QSTile <span class="title function_">createTile</span><span class="params">(String tileSpec)</span> &#123;</span><br><span class="line">    <span class="type">QSTileImpl</span> <span class="variable">tile</span> <span class="operator">=</span> createTileInternal(tileSpec);</span><br><span class="line">    <span class="keyword">if</span> (tile != <span class="literal">null</span>) &#123;</span><br><span class="line">        tile.handleStale(); <span class="comment">// Tile was just created, must be stale.</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> tile;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">private</span> QSTileImpl <span class="title function_">createTileInternal</span><span class="params">(String tileSpec)</span> &#123;</span><br><span class="line">    <span class="comment">// 省略其他代码......</span></span><br><span class="line">    <span class="comment">// Stock tiles.</span></span><br><span class="line">    <span class="keyword">switch</span> (tileSpec) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;wifi&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mWifiTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;internet&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mInternetTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;bt&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mBluetoothTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;cell&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mCellularTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;dnd&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mDndTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;inversion&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mColorInversionTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;airplane&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mAirplaneModeTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;work&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mWorkModeTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;rotation&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mRotationLockTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;flashlight&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mFlashlightTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;location&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mLocationTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;cast&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mCastTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;hotspot&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mHotspotTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;battery&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mBatterySaverTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;saver&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mDataSaverTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;night&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mNightDisplayTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;nfc&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mNfcTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;dark&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mUiModeNightTileProvider.get();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;screenrecord&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> mScreenRecordTileProvider.get();</span><br><span class="line">            <span class="comment">// 省略其他代码......</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 省略其他代码......</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>看到这里通过对应的字符串分别实例化了对应的 Tile。</p>
<h2 id="2、QS显示"><a href="#2、QS显示" class="headerlink" title="2、QS显示"></a>2、QS显示</h2><p>以上涉及资源文件加载及对应实例化，接下来看看如何显示出来的。和Android 11 对比出入有点大，加了一个控制器。<br>这里要回到 QSFragment#onViewCreated() 方法：<br><strong>com.android.systemui.qs.QSFragment.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onViewCreated</span><span class="params">(View view, <span class="meta">@Nullable</span> Bundle savedInstanceState)</span> &#123;</span><br><span class="line">    <span class="type">QSFragmentComponent</span> <span class="variable">qsFragmentComponent</span> <span class="operator">=</span> mQsComponentFactory.create(<span class="built_in">this</span>);</span><br><span class="line">    mQSPanelController = qsFragmentComponent.getQSPanelController();</span><br><span class="line">    mQuickQSPanelController = qsFragmentComponent.getQuickQSPanelController();</span><br><span class="line">    mQSFooterActionController = qsFragmentComponent.getQSFooterActionController();</span><br><span class="line">    <span class="comment">// 一些初始化，init() 是 抽象类 ViewController 的 public 方法。</span></span><br><span class="line">    mQSPanelController.init();</span><br><span class="line">    mQuickQSPanelController.init();</span><br><span class="line">    mQSFooterActionController.init();</span><br><span class="line">    <span class="comment">// 扩展的 qs 滚动视图</span></span><br><span class="line">    mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view); </span><br><span class="line">    <span class="comment">// 省略其他代码......</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>经过上述分析，我们来看看 ViewController#init()：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (mInited) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    onInit();    <span class="comment">// 要在 onViewAttached() 方法之前运行，</span></span><br><span class="line">    mInited = <span class="literal">true</span>;</span><br><span class="line">    <span class="keyword">if</span> (isAttachedToWindow()) &#123;</span><br><span class="line">        <span class="comment">// 调用内部 onViewAttachedToWindow() 方法，去添加视图。</span></span><br><span class="line">        mOnAttachStateListener.onViewAttachedToWindow(mView);</span><br><span class="line">    &#125;</span><br><span class="line">    addOnAttachStateChangeListener(mOnAttachStateListener);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="type">OnAttachStateChangeListener</span> <span class="variable">mOnAttachStateListener</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">OnAttachStateChangeListener</span>() &#123;</span><br><span class="line">      <span class="meta">@Override</span></span><br><span class="line">      <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onViewAttachedToWindow</span><span class="params">(View v)</span> &#123;</span><br><span class="line">          <span class="comment">// 调用自己的抽象方法 onViewAttached() ，在子类具体实现，添加 Tiles.</span></span><br><span class="line">          ViewController.<span class="built_in">this</span>.onViewAttached();</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="meta">@Override</span></span><br><span class="line">      <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onViewDetachedFromWindow</span><span class="params">(View v)</span> &#123;</span><br><span class="line">          ViewController.<span class="built_in">this</span>.onViewDetached();</span><br><span class="line">      &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>这个添加在 QSPanelController 的父类 QSPanelControllerBase 中的 onViewAttached() 方法中。<br>QSPanelControllerBase#onViewAttached()<br><strong>com.android.systemui.qs.QSPanelControllerBase.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">onViewAttached</span><span class="params">()</span> &#123;</span><br><span class="line">    mQsTileRevealController = createTileRevealController();</span><br><span class="line">    <span class="keyword">if</span> (mQsTileRevealController != <span class="literal">null</span>) &#123;</span><br><span class="line">        mQsTileRevealController.setExpansion(mRevealExpansion);</span><br><span class="line">    &#125;</span><br><span class="line">    mMediaHost.addVisibilityChangeListener(mMediaHostVisibilityListener);</span><br><span class="line">    mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);</span><br><span class="line">    mHost.addCallback(mQSHostCallback);</span><br><span class="line">    <span class="comment">// 这里设置 Tiles</span></span><br><span class="line">    setTiles();</span><br><span class="line">    mLastOrientation = getResources().getConfiguration().orientation;</span><br><span class="line">    switchTileLayout(<span class="literal">true</span>);</span><br><span class="line">    mDumpManager.registerDumpable(mView.getDumpableTag(), <span class="built_in">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/** */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setTiles</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">// 这里 getTiles() 就是获取，前面我们说的 Tiles 实例，在 QSTileHost 中。</span></span><br><span class="line">    setTiles(mHost.getTiles(), <span class="literal">false</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/** */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setTiles</span><span class="params">(Collection&lt;QSTile&gt; tiles, <span class="type">boolean</span> collapsedView)</span> &#123;</span><br><span class="line">    <span class="comment">// TODO(b/168904199): move this logic into QSPanelController.</span></span><br><span class="line">    <span class="keyword">if</span> (!collapsedView &amp;&amp; mQsTileRevealController != <span class="literal">null</span>) &#123;</span><br><span class="line">        mQsTileRevealController.updateRevealedTiles(tiles);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (QSPanelControllerBase.TileRecord record : mRecords) &#123;</span><br><span class="line">        mView.removeTile(record);</span><br><span class="line">        record.tile.removeCallback(record.callback);</span><br><span class="line">    &#125;</span><br><span class="line">    mRecords.clear();</span><br><span class="line">    mCachedSpecs = <span class="string">&quot;&quot;</span>;</span><br><span class="line">    <span class="keyword">for</span> (QSTile tile : tiles) &#123;</span><br><span class="line">        addTile(tile, collapsedView);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">addTile</span><span class="params">(<span class="keyword">final</span> QSTile tile, <span class="type">boolean</span> collapsedView)</span> &#123;</span><br><span class="line">    <span class="comment">// 这里会创建对应的视图。</span></span><br><span class="line">    <span class="keyword">final</span> <span class="type">TileRecord</span> <span class="variable">r</span> <span class="operator">=</span></span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">TileRecord</span>(tile, mHost.createTileView(getContext(), tile, collapsedView));</span><br><span class="line">    <span class="comment">// 注意：这个  mView 是 QSPanel，在 QSPanelController 的构造方法通过super传到 QSPanelControllerBase 的。这里也是视图的添加。</span></span><br><span class="line">    mView.addTile(r);</span><br><span class="line">    mRecords.add(r);</span><br><span class="line">    mCachedSpecs = getTilesSpecs();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里只需关注QSPanel#addTile():<br><strong>com.android.systemui.qs.QSPanel.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> <span class="title function_">addTile</span><span class="params">(QSPanelControllerBase.TileRecord tileRecord)</span> &#123;</span><br><span class="line">    <span class="keyword">final</span> QSTile.<span class="type">Callback</span> <span class="variable">callback</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QSTile</span>.Callback() &#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onStateChanged</span><span class="params">(QSTile.State state)</span> &#123;</span><br><span class="line">            drawTile(tileRecord, state);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    tileRecord.tile.addCallback(callback);</span><br><span class="line">    tileRecord.callback = callback;</span><br><span class="line">    tileRecord.tileView.init(tileRecord.tile);</span><br><span class="line">    tileRecord.tile.refreshState();</span><br><span class="line">    <span class="keyword">if</span> (mTileLayout != <span class="literal">null</span>) &#123;</span><br><span class="line">        mTileLayout.addTile(tileRecord);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>由 TileLayout#addTile() 实现:<br><strong>com.android.systemui.qs.TileLayout.java</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addTile</span><span class="params">(TileRecord tile)</span> &#123;</span><br><span class="line">    mRecords.add(tile);</span><br><span class="line">    tile.tile.setListening(<span class="built_in">this</span>, mListening);</span><br><span class="line">    addTileView(tile);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">addTileView</span><span class="params">(TileRecord tile)</span> &#123;</span><br><span class="line">    <span class="comment">// 注：TileLayout 继承的是 ViewGroup。</span></span><br><span class="line">    addView(tile.tileView);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>至此，SystemUI 下拉状态栏快捷开关模块代码流程分析完毕。<br>QS一个有3种呈现方式，如图：<br><img src="/images/20230522/Screenshot_20230522-205519.jpg"></p>
<p>我这分析的是第 2 种。其他的展示方法也类似。<br><strong>res/layout/qs_panel.xml</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">com.android.systemui.qs.QSContainerImpl</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">xmlns:tools</span>=<span class="string">&quot;http://schemas.android.com/tools&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/quick_settings_container&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:clipToPadding</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:clipChildren</span>=<span class="string">&quot;false&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 第二种布局 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">com.android.systemui.qs.NonInterceptingScrollView</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/expanded_qs_scroll_view&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:elevation</span>=<span class="string">&quot;@dimen/qs_panel_elevation&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:importantForAccessibility</span>=<span class="string">&quot;no&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:scrollbars</span>=<span class="string">&quot;none&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:clipChildren</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:clipToPadding</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_weight</span>=<span class="string">&quot;1&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">com.android.systemui.qs.QSPanel</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:id</span>=<span class="string">&quot;@+id/quick_settings_panel&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:background</span>=<span class="string">&quot;@android:color/transparent&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:focusable</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:accessibilityTraversalBefore</span>=<span class="string">&quot;@android:id/edit&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:clipToPadding</span>=<span class="string">&quot;false&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:clipChildren</span>=<span class="string">&quot;false&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">include</span> <span class="attr">layout</span>=<span class="string">&quot;@layout/qs_footer_impl&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">com.android.systemui.qs.QSPanel</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">com.android.systemui.qs.NonInterceptingScrollView</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 第一种布局 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">include</span> <span class="attr">layout</span>=<span class="string">&quot;@layout/quick_status_bar_expanded_header&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">include</span></span></span><br><span class="line"><span class="tag">        <span class="attr">layout</span>=<span class="string">&quot;@layout/footer_actions&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/qs_footer_actions&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;@dimen/footer_actions_height&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_gravity</span>=<span class="string">&quot;bottom&quot;</span></span></span><br><span class="line"><span class="tag">        /&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 第三种布局 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">include</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/qs_customize&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">layout</span>=<span class="string">&quot;@layout/qs_customize_panel&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:visibility</span>=<span class="string">&quot;gone&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">com.android.systemui.qs.QSContainerImpl</span>&gt;</span></span><br></pre></td></tr></table></figure>

      
      <blockquote>
        
        <strong>本文链接：</strong><br><a href="http://longzhiye.top/2023/05/22/2023-05-22/">http://longzhiye.top/2023/05/22/2023-05-22/</a>
      </blockquote>
    </div>
    <footer class="mdui-card-actions">
      
        <a class="mdui-ripple article_categories-link" href="/categories/%E6%8A%80%E6%9C%AF/">技术</a>
      
      
        <a class="mdui-ripple article_tags-link" href="/tags/Android/" rel="tag">Android</a><a class="mdui-ripple article_tags-link" href="/tags/Framework/" rel="tag">Framework</a><a class="mdui-ripple article_tags-link" href="/tags/SystemUI/" rel="tag">SystemUI</a>
      
    </footer>
    
  </article>
  
<script src="//cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script>

  <script>$("#main article .mdui-card-content img.fancybox").on("click",function(e){$.fancybox.open({src:$(this).attr("src")});});</script>


  <nav id="paginator">
    
      <a rel="prev" class="extend prev" href="/2023/06/25/2023-06-25/">
        <button aria-label="prev" class="mdui-btn mdui-btn-raised mdui-btn-icon mdui-color-theme-accent mdui-ripple"><i class="mdui-icon material-icons">arrow_back</i></button>
        <span class="mdui-p-x-3" mdui-tooltip="{content: '如何让Android设备实现息屏显示'}">上一篇</span>
      </a>
    
    <div class="spacer"></div>
    
      <a rel="next" class="extend next" href="/2023/05/21/2023-05-21/">
        <span class="mdui-p-x-3" mdui-tooltip="{content: 'Android13源码下载和编译过程详解'}">下一篇</span>
        <button aria-label="next" class="mdui-btn mdui-btn-raised mdui-btn-icon mdui-color-theme-accent mdui-ripple"><i class="mdui-icon material-icons">arrow_forward</i></button>
      </a>
    
  </nav>





</main>
  <footer id="footer" class="mdui-m-t-5 mdui-p-y-3 mdui-color-theme">
  <div class="mdui-p-y-0 mdui-text-center">
    
    
    
    
    
    
    
      <a href="http://github.com/longzhiye" target="_blank" class="mdui-btn mdui-btn-icon mdui-text-color-theme-a100"><i class="mdui-icon iconfont">&#xe7ab;</i></a>
    
    
    
      <a href="https://www.zhihu.com/people/long-zhi-xie-61" target="_blank" class="mdui-btn mdui-btn-icon mdui-text-color-theme-a100"><i class="mdui-icon iconfont">&#xe6c0;</i></a>
    
    
    
      <a href="tencent://tencent:////message/?uin=951898105&Menu=yes" target="_blank" class="mdui-btn mdui-btn-icon mdui-text-color-theme-a100"><i class="mdui-icon iconfont">&#xe651;</i></a>
    
    
  </div>
  <div class="mdui-p-y-1 mdui-text-center">
    Copyright &copy; 2022 - 2025 龙之叶<br>
    Powered by <a href="https://hexo.io/" target="_blank" class="mdui-text-color-theme-accent">Hexo</a>
    <br>
      <span id="busuanzi_container_site_pv" style="display: none;"><i class="iconfont">&#xe7fd;</i> <span id="busuanzi_value_site_pv"></span></span> &nbsp;&nbsp;
      <span id="busuanzi_container_site_uv" style="display: none;"><i class="iconfont">&#xe601;</i> <span id="busuanzi_value_site_uv"></span></span>
    
  </div>
</footer>

  <button id="gotop" class="mdui-fab mdui-fab-fixed mdui-fab-hide mdui-color-theme-accent mdui-ripple"><i class="mdui-icon material-icons">arrow_upward</i></button>
  <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
  
<script src="/js/mdui.js"></script>
<script src="/js/script.js"></script>

  
<script src="/custom.js"></script>

</body>
</html>
